/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#include "Keyboard.h"
#include <sstream>

namespace liba
{
namespace input
{
namespace hard
{
namespace marmalade
{

/* These are the Macintosh key scancode constants -- from Inside Macintosh */

#define MK_ESCAPE		0x35
#define MK_F1			0x7A
#define MK_F2			0x78
#define MK_F3			0x63
#define MK_F4			0x76
#define MK_F5			0x60
#define MK_F6			0x61
#define MK_F7			0x62
#define MK_F8			0x64
#define MK_F9			0x65
#define MK_F10			0x6D
#define MK_F11			0x67
#define MK_F12			0x6F
#define MK_PRINT		0x69
#define MK_SCROLLOCK		0x6B
#define MK_PAUSE		0x71
#define MK_POWER		0x7F
#define MK_BACKQUOTE		0x32
#define MK_1			0x12
#define MK_2			0x13
#define MK_3			0x14
#define MK_4			0x15
#define MK_5			0x17
#define MK_6			0x16
#define MK_7			0x1A
#define MK_8			0x1C
#define MK_9			0x19
#define MK_0			0x1D
#define MK_MINUS		0x1B
#define MK_EQUALS		0x18
#define MK_BACKSPACE		0x33
#define MK_INSERT		0x72
#define MK_HOME			0x73
#define MK_PAGEUP		0x74
#define MK_NUMLOCK		0x47
#define MK_KP_EQUALS		0x51
#define MK_KP_DIVIDE		0x4B
#define MK_KP_MULTIPLY		0x43
#define MK_TAB			0x30
#define MK_q			0x0C
#define MK_w			0x0D
#define MK_e			0x0E
#define MK_r			0x0F
#define MK_t			0x11
#define MK_y			0x10
#define MK_u			0x20
#define MK_i			0x22
#define MK_o			0x1F
#define MK_p			0x23
#define MK_LEFTBRACKET		0x21
#define MK_RIGHTBRACKET		0x1E
#define MK_BACKSLASH		0x2A
#define MK_DELETE		0x75
#define MK_END			0x77
#define MK_PAGEDOWN		0x79
#define MK_KP7			0x59
#define MK_KP8			0x5B
#define MK_KP9			0x5C
#define MK_KP_MINUS		0x4E
#define MK_CAPSLOCK		0x39
#define MK_a			0x00
#define MK_s			0x01
#define MK_d			0x02
#define MK_f			0x03
#define MK_g			0x05
#define MK_h			0x04
#define MK_j			0x26
#define MK_k			0x28
#define MK_l			0x25
#define MK_SEMICOLON		0x29
#define MK_QUOTE		0x27
#define MK_RETURN		0x24
#define MK_KP4			0x56
#define MK_KP5			0x57
#define MK_KP6			0x58
#define MK_KP_PLUS		0x45
#define MK_LSHIFT		0x38
#define MK_z			0x06
#define MK_x			0x07
#define MK_c			0x08
#define MK_v			0x09
#define MK_b			0x0B
#define MK_n			0x2D
#define MK_m			0x2E
#define MK_COMMA		0x2B
#define MK_PERIOD		0x2F
#define MK_SLASH		0x2C
#if 0	/* These are the same as the left versions - use left by default */
#define MK_RSHIFT		0x38
#endif
#define MK_UP			0x7E
#define MK_KP1			0x53
#define MK_KP2			0x54
#define MK_KP3			0x55
#define MK_KP_ENTER		0x4C
#define MK_LCTRL		0x3B
#define MK_LALT			0x3A
#define MK_LMETA		0x37
#define MK_SPACE		0x31
#if 0	/* These are the same as the left versions - use left by default */
#define MK_RMETA		0x37
#define MK_RALT			0x3A
#define MK_RCTRL		0x3B
#endif
#define MK_LEFT			0x7B
#define MK_DOWN			0x7D
#define MK_RIGHT		0x7C
#define MK_KP0			0x52
#define MK_KP_PERIOD		0x41

/* Wierd, these keys are on my iBook under MacOS X */
#define MK_IBOOK_ENTER		0x34
#define MK_IBOOK_LEFT		0x3B
#define MK_IBOOK_RIGHT		0x3C
#define MK_IBOOK_DOWN		0x3D
#define MK_IBOOK_UP		0x3E


Keyboard::Keyboard()
:	symbol_symap( 0, "KeyNone" )
{

	symbol_symap.add( MK_ESCAPE, "Esc" );
	symbol_symap.add( MK_RETURN, "Enter" );
	symbol_symap.add( MK_LEFT, "Left" );
	symbol_symap.add( MK_UP, "Up" );
	symbol_symap.add( MK_RIGHT, "Right" );
	symbol_symap.add( MK_DOWN, "Down" );
	symbol_symap.add( MK_SPACE, "Space" );
	symbol_symap.add( MK_DELETE, "Delete" );
	symbol_symap.add( MK_BACKSPACE, "BackSpace" );
	symbol_symap.add( MK_LSHIFT, "Shift" );
	symbol_symap.add( MK_LCTRL, "Ctrl" );
	symbol_symap.add( MK_EQUALS, "Plus" );
	symbol_symap.add( MK_MINUS, "Minus" );
	symbol_symap.add( MK_TAB, "Tab" );
	symbol_symap.add( MK_F1, "F1" );
	symbol_symap.add( MK_F2, "F2" );
	symbol_symap.add( MK_F3, "F3" );
	symbol_symap.add( MK_F4, "F4" );
	symbol_symap.add( MK_F5, "F5" );
	symbol_symap.add( MK_F6, "F6" );
	symbol_symap.add( MK_F7, "F7" );
	symbol_symap.add( MK_F8, "F8" );
	symbol_symap.add( MK_F9, "F9" );
	symbol_symap.add( MK_F10, "F10" );
	symbol_symap.add( MK_F11, "F11" );
	symbol_symap.add( MK_F12, "F12" );

	symbol_symap.add( MK_0, "0" );
	symbol_symap.add( MK_1, "1" );
	symbol_symap.add( MK_2, "2" );
	symbol_symap.add( MK_3, "3" );
	symbol_symap.add( MK_4, "4" );
	symbol_symap.add( MK_5, "5" );
	symbol_symap.add( MK_6, "6" );
	symbol_symap.add( MK_7, "7" );
	symbol_symap.add( MK_8, "8" );
	symbol_symap.add( MK_9, "9" );

	symbol_symap.add( MK_a, "A" );
	symbol_symap.add( MK_b, "B" );
	symbol_symap.add( MK_c, "C" );
	symbol_symap.add( MK_d, "D" );
	symbol_symap.add( MK_e, "E" );
	symbol_symap.add( MK_f, "F" );
	symbol_symap.add( MK_g, "G" );
	symbol_symap.add( MK_h, "H" );
	symbol_symap.add( MK_i, "I" );
	symbol_symap.add( MK_j, "J" );
	symbol_symap.add( MK_k, "K" );
	symbol_symap.add( MK_l, "L" );
	symbol_symap.add( MK_m, "M" );
	symbol_symap.add( MK_n, "N" );
	symbol_symap.add( MK_o, "O" );
	symbol_symap.add( MK_p, "P" );
	symbol_symap.add( MK_q, "Q" );
	symbol_symap.add( MK_r, "R" );
	symbol_symap.add( MK_s, "S" );
	symbol_symap.add( MK_t, "T" );
	symbol_symap.add( MK_u, "U" );
	symbol_symap.add( MK_v, "V" );
	symbol_symap.add( MK_w, "W" );
	symbol_symap.add( MK_x, "X" );
	symbol_symap.add( MK_y, "Y" );
	symbol_symap.add( MK_z, "Z" );

	for( int i = 0; i < 256; ++i )
	{
		if( !symbol_symap.is_exists_first( i ) )
		{
			std::stringstream ss;
			ss << "Key#" << i;
			symbol_symap.add( i, ss.str() );
		}
	}
}

Keyboard::~Keyboard()
{}

void Keyboard::key_up( int scan_code )
{
	Manager::add_event( Event( get_name(), get_name_by_code( scan_code ), false ) );
}

void Keyboard::key_down( int scan_code )
{
	Manager::add_event( Event( get_name(), get_name_by_code( scan_code ), true ) );
}

void Keyboard::key_char( wchar_t letter )
{
	Manager::add_event( Event( get_name(), std::wstring( 1, letter ) ) );
}

std::string Keyboard::get_name()const
{
	return "Keyboard";
}

double Keyboard::get_axis_position( const std::string & axis_name )const
{
	THROW("Unimplemented");
/*	int scan_code = get_code_by_name( axis_name );
	SHORT state = GetAsyncKeyState( scan_code );

	bool pressed = state & 0x8000;
	return pressed;*/
	return 0;
}

Manager::AxisType Keyboard::get_axis_type( const std::string & axis_name )const
{
	if( symbol_symap.is_exists_second( axis_name ) )
		return Manager::BUTTON;

	return Manager::NONE;
}

std::string Keyboard::get_name_by_code( int scan_code )const
{
	return symbol_symap.get_second_by_first( scan_code );
}

int Keyboard::get_code_by_name( const std::string & name )const
{
	return symbol_symap.get_first_by_second( name );
}

hard::ForceEffect * Keyboard::create_force_effect( const filesystem::String & effect_name )
{
	return new ForceEffect();
}
	
bool ForceEffect::play()
{
	return true;
}

} // namespace marmalade
} // namespace hard
} // namespace input
} // namespace liba


